﻿using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;
using System;


namespace ChangDiTools.Demo {
    public class IntersectionCal {
        //

        [CommandMethod("LineToLineIntersection")]
        public void LineToLineIntersection() {
            Document doc = Application.DocumentManager.MdiActiveDocument;
            Editor editor = doc.Editor;
            Database db = doc.Database;
            Entity entity1 = SelectEntity("Select Line");
            Entity entity2 = SelectEntity("Select Line");
            using (Transaction trans = db.TransactionManager.StartOpenCloseTransaction()) {

                BlockTable bt = trans.GetObject(db.BlockTableId, OpenMode.ForWrite) as BlockTable;
                BlockTableRecord btr = trans.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite) as BlockTableRecord;
                Line line1 = entity1 as Line;
                Line line2 = entity2 as Line;
                Point3dCollection intersectionPts = new Point3dCollection();
                line1.IntersectWith(line2, Intersect.OnBothOperands, intersectionPts, IntPtr.Zero, IntPtr.Zero);
                if (intersectionPts.Count >= 1) {
                    foreach (Point3d pt in intersectionPts) {
                        if (pt != line1.StartPoint && pt != line1.EndPoint && pt != line2.StartPoint && pt != line2.EndPoint) {
                            Polyline pLine = new Polyline();
                            double distance = line1.StartPoint.DistanceTo(pt);
                            Point3d ptLeft = line1.GetPointAtDist(distance - line1.Length / 20);
                            Point3d ptRight = line1.GetPointAtDist(distance + line1.Length / 20);
                            pLine.AddVertexAt(0, new Point2d(line1.StartPoint.X, line1.StartPoint.Y), 0, 0, 0);
                            pLine.AddVertexAt(1, new Point2d(ptLeft.X, ptLeft.Y), 1, 0, 0);
                            pLine.AddVertexAt(2, new Point2d(ptRight.X, ptRight.Y), 0, 0, 0);
                            pLine.AddVertexAt(3, new Point2d(line1.EndPoint.X, line1.EndPoint.Y), 0, 0, 0);
                            btr.AppendEntity(pLine);
                            trans.AddNewlyCreatedDBObject(pLine, true);
                            DBObject dbObj = trans.GetObject(line1.ObjectId, OpenMode.ForWrite);
                            dbObj.Erase();
                        }
                    }
                }
                trans.Commit();
            }
        }

        //直线相交，将其中一条直线 line1 变为多段线，交点附近以圆弧显示
        public static void InterSectionToArc(Line line1, Line line2) {
            Document doc = Application.DocumentManager.MdiActiveDocument;
            Editor editor = doc.Editor;
            Database db = doc.Database;
            using (Transaction trans = db.TransactionManager.StartOpenCloseTransaction()) {
                BlockTable bt = trans.GetObject(db.BlockTableId, OpenMode.ForWrite) as BlockTable;
                BlockTableRecord btr = trans.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite) as BlockTableRecord;
                Point3dCollection intersectionPts = new Point3dCollection();
                line1.IntersectWith(line2, Intersect.OnBothOperands, intersectionPts, IntPtr.Zero, IntPtr.Zero);
                if (intersectionPts.Count >= 1) {
                    foreach (Point3d pt in intersectionPts) {
                        if (pt != line1.StartPoint && pt != line1.EndPoint && pt != line2.StartPoint && pt != line2.EndPoint) {
                            Polyline pLine = new Polyline();
                            double distance = line1.StartPoint.DistanceTo(pt);
                            Point3d ptLeft = line1.GetPointAtDist(distance - line1.Length / 10);
                            Point3d ptRight = line1.GetPointAtDist(distance + line1.Length / 10);
                            pLine.AddVertexAt(0, new Point2d(line1.StartPoint.X, line1.StartPoint.Y), 0, 0, 0);
                            pLine.AddVertexAt(1, new Point2d(ptLeft.X, ptLeft.Y), 1, 0, 0);
                            pLine.AddVertexAt(2, new Point2d(ptRight.X, ptRight.Y), 0, 0, 0);
                            pLine.AddVertexAt(3, new Point2d(line1.EndPoint.X, line1.EndPoint.Y), 0, 0, 0);
                            btr.AppendEntity(pLine);
                            trans.AddNewlyCreatedDBObject(pLine, true);
                            DBObject dbObj = trans.GetObject(line1.ObjectId, OpenMode.ForWrite);
                            dbObj.Erase();
                        }
                    }
                }
                trans.Commit();
            }
        }


        [CommandMethod("DrawPyLineWithArc")]
        public void DrawPyLineWithArc() {

            Document doc = Application.DocumentManager.MdiActiveDocument;
            Editor editor = doc.Editor;
            Database db = doc.Database;
            using (Transaction trans = db.TransactionManager.StartOpenCloseTransaction()) {
                BlockTable bt = trans.GetObject(db.BlockTableId, OpenMode.ForWrite) as BlockTable;
                BlockTableRecord btr = trans.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite) as BlockTableRecord;
                Polyline pLine = new Polyline();
                //pLine.StartPoint = new Point3d(0, 0, 0);
                pLine.AddVertexAt(0, new Point2d(0, 0), 0, 0, 0);
                pLine.AddVertexAt(1, new Point2d(200, 0), 1, 0, 0);
                pLine.AddVertexAt(2, new Point2d(300, 0), 0, 0, 0);
                pLine.AddVertexAt(3, new Point2d(1000, 0), 0, 0, 0);
                //pLine.EndPoint = new Point3d(400, 0, 0);
                btr.AppendEntity(pLine);
                trans.AddNewlyCreatedDBObject(pLine, true);
                trans.Commit();
            }
        }

        [CommandMethod("NumberPolyLine")]
        public void NumberPolyLine() {
            Entity entity = SelectEntity("Select An PolyLine");
            Polyline pLine = entity as Polyline;
            Document doc = Application.DocumentManager.MdiActiveDocument;
            Editor editor = doc.Editor;
            editor.WriteMessage("\n========" + pLine.NumberOfVertices);
            int count = pLine.NumberOfVertices;
            for (int i = 0; i < count; i++) {
                double bulge = pLine.GetBulgeAt(i);
                Point3d pt = pLine.GetPoint3dAt(i);
                editor.WriteMessage("\n i is {0} and the bulge is {1}, and Point is : {2}", i, bulge, pt.ToString());
            }
        }


        [CommandMethod("CircleAndLineIntersection")]
        public void CircleAndLineIntersection() {
            Document doc = Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor editor = doc.Editor;
            Entity entity1 = SelectEntity("Select Line");
            Entity entity2 = SelectEntity("Select Circle");
            using (Transaction trans = db.TransactionManager.StartTransaction()) {
                Line line = entity1 as Line;
                Circle circle = entity2 as Circle;

                Point3dCollection intersectionPoints = new Point3dCollection();
                line.IntersectWith(circle, Intersect.OnBothOperands, intersectionPoints, IntPtr.Zero, IntPtr.Zero);
                trans.Commit();
                editor.WriteMessage("\n {0} intersection(s) is found", intersectionPoints.Count);
                foreach (Point3d point in intersectionPoints) {
                    editor.WriteMessage("\n intersection coordinate is: " + point.ToString());
                }

            }
        }


        [CommandMethod("BlRefAndLineIntersection")]
        public void RlRefAndLineIntersection() {
            Document doc = Application.DocumentManager.MdiActiveDocument;
            Editor editor = doc.Editor;
            Database db = doc.Database;
            Entity lineEntity = SelectEntity("Select A Line");
            Entity blRefEntity = SelectEntity("Select A BlockReference");
            using (Transaction trans = db.TransactionManager.StartTransaction()) {
                Line line = lineEntity as Line;
                BlockReference blRef = blRefEntity as BlockReference;
                Point3dCollection intersectionPoints = new Point3dCollection();
                line.IntersectWith(blRef, Intersect.OnBothOperands, intersectionPoints, IntPtr.Zero, IntPtr.Zero);
                trans.Commit();
                editor.WriteMessage("\n {0} intersection(s) is found", intersectionPoints.Count);
                foreach (Point3d point in intersectionPoints) {
                    editor.WriteMessage("\n intersection coordinate is: " + point.ToString());
                }

            }
        }


        public static Point3dCollection BlRefAndLineIntersectCal() {
            Document doc = Application.DocumentManager.MdiActiveDocument;
            Editor editor = doc.Editor;
            Database db = doc.Database;
            Entity lineEntity = SelectEntity("Select A Line");
            Entity blRefEntity = SelectEntity("Select A BlockReference");
            Point3dCollection intersectionPoints = null;
            using (Transaction trans = db.TransactionManager.StartTransaction()) {
                Line line = lineEntity as Line;
                BlockReference blRef = blRefEntity as BlockReference;
                intersectionPoints = new Point3dCollection();
                line.IntersectWith(blRef, Intersect.OnBothOperands, intersectionPoints, IntPtr.Zero, IntPtr.Zero);
                trans.Commit();
                editor.WriteMessage("\n {0} intersection(s) is found", intersectionPoints.Count);
                foreach (Point3d point in intersectionPoints) {
                    editor.WriteMessage("\n intersection coordinate is: " + point.ToString());
                }

            }
            return intersectionPoints;
        }
        public static Entity SelectEntity(string infomation) {
            Document doc = Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor editor = doc.Editor;
            Entity entity = null;
            PromptEntityResult re = editor.GetEntity(infomation);
            if (re.Status == PromptStatus.OK) {
                using (Transaction transaction = db.TransactionManager.StartTransaction()) {

                    DBObject dbObject = transaction.GetObject(re.ObjectId, OpenMode.ForWrite, true);
                    //editor.WriteMessage("\n DBOBject=======" + dbObject.ToString());
                    entity = (Entity)dbObject;
                    //Application.ShowAlertDialog("Handle=========" + entity.ObjectId.Handle);
                    transaction.Commit();
                }
            }
            return entity;
        }
    }
}
